//
//  main.cpp
//  
//
//  Created by Kun Zhao on 12/12/05.
//  Copyright (c) 2012 Kyoto University. All rights reserved.
//

#include <iostream>
#include <kvs/glut/Application>
#include <kvs/glut/Screen>
#include <kvs/StructuredVolumeObject>
#include <kvs/StructuredVolumeImporter>
#include <kvs/HydrogenVolumeData>
#include <kvs/CommandLine>
#include "RayCastingRenderer.h"
#include "TransferFunction3D.h"

class Argument : public kvs::CommandLine
{
public:
     
    std::string directory;
  std::string tfunc_file;
    
    Argument( int argc, char** argv ) : CommandLine( argc, argv )
    {
        add_help_option();
        addOption( "d", "directory name of the data", 1, true );
        addOption( "O", "use the OW transfer function", 0, false );
        addOption( "T", "use the OW and TW transfer function", 0, false );
	addOption( "t", "use the assigned transfer function", 1, false );
    }
    
    void exec()
    {
        if( !this->parse() ) exit( EXIT_FAILURE );
        if( this->hasOption( "d" ) ) directory = this->optionValue<std::string>( "d" );
	if( this->hasOption( "t" ) ) tfunc_file = this->optionValue<std::string>( "t" );
    }
    
};

int main( int argc, char** argv )
{
    kvs::glut::Application app( argc, argv );
    kvs::glut::Screen screen( &app );
    
    Argument param( argc, argv );
    param.exec();
    
    kvs::StructuredVolumeObject* volume_s = new kvs::StructuredVolumeImporter( param.directory + "s.kvsml" );
    kvs::StructuredVolumeObject* volume_r = new kvs::StructuredVolumeImporter( param.directory + "rhoo.kvsml" );
    kvs::StructuredVolumeObject* volume_v = new kvs::StructuredVolumeImporter( param.directory + "velocity.kvsml");
//    volume_v->setMinMaxValues( 0.0, 306.863 );
        volume_v->setMinMaxValues( 0.0, 306.863 );
    
   //  // set the 3d transfer function
   // size_t size = 64;
   // size_t width = size;
   // size_t height = size;
   // size_t depth = size;
   // float* tfunc3d = new float[width * height * depth * 4];
   // for ( size_t k = 0; k < depth; k++ )
   //     for ( size_t j = 0; j < height; j++ )
   //         for ( size_t i = 0; i < width; i++ )
   //         {
   //             int index = ( i + j * width + k * width * height ) * 4;
   //             tfunc3d[index] = (float)i / width;      // red
   //             tfunc3d[index + 1] = (float)j / height; // green
   //             tfunc3d[index + 2] = 1;                 // blue
   //             tfunc3d[index + 3] = (float)k / depth;  // alpha
   //         }
    
    kun::TransferFunction3D tfunc3d;
   size_t size = 40;
   size_t width = 100;
   size_t height = 600;
   size_t depth = size;
   tfunc3d.setResolution(kvs::Vector3f( width, height, depth) );
   float* tfunc3d_data = new float[width * height * depth * 4];
   float max_opacity = 1;
   for ( size_t k = 0; k < depth; k++ )
       for ( size_t j = 0; j < height; j++ )
           for ( size_t i = 0; i < width; i++ )
           {
               int index = ( i + j * width + k * width * height ) * 4;
	       float opacity;
	       if ( k > 15 ) 
		 opacity = 1;
               else
		 opacity = ((float)k / 15) * max_opacity;
               if ( i < 39 )
               {
                   tfunc3d_data[index] = 0;      // red
                   tfunc3d_data[index + 1] = 0;  // green
                   tfunc3d_data[index + 2] = 0;  // blue
                   tfunc3d_data[index + 3] = 0;
               }
                   
               if ( 39 <= i && i <= 52 ) // blue
               {
                   tfunc3d_data[index] = 0;      // red
                   tfunc3d_data[index + 1] = 0;  // green
                   tfunc3d_data[index + 2] = 1;  // blue
                   tfunc3d_data[index + 3] = opacity;
               }
               if ( 52 < i && i <= 70 ) // yellow
               {
                   tfunc3d_data[index] = 1;      // red
                   tfunc3d_data[index + 1] = 1;  // green
                   tfunc3d_data[index + 2] = 0;  // blue
                   tfunc3d_data[index + 3] = 0;
               }
               if ( 70 < i && i < 100 ) // red
               {
                   // if( 0 <= j && j < 5 ) // yellow
                   // {
                   //     tfunc3d_data[index] = 1;      // red
                   //     tfunc3d_data[index + 1] = 1;  // green
                   //     tfunc3d_data[index + 2] = 1;  // blue
                   //     tfunc3d_data[index + 3] = 0;
                   // }
                   // else
                   // {
                   //     if ( 27 < i && i <= 32 )  // green
                   //     {
                           // tfunc3d_data[index] = 0;      // red
                           // tfunc3d_data[index + 1] = 1;  // green
                           // tfunc3d_data[index + 2] = 0;  // blue
                           // tfunc3d_data[index + 3] = opacity;
                   //     }
                   //     else // red
                   //     {
                   //         tfunc3d_data[index] = 1;      // red
                   //         tfunc3d_data[index + 1] = 0;  // green
                   //         tfunc3d_data[index + 2] = 0;  // blue
                   //         tfunc3d_data[index + 3] = 0;
                   //     }
		 if( 67 < i && i <= 80 && 522 <= j && j <= 563 )
		   {
                           tfunc3d_data[index] = 0;      // red
                           tfunc3d_data[index + 1] = 1;  // green
                           tfunc3d_data[index + 2] = 0;  // blue
			   tfunc3d_data[index + 3] = opacity;
                   }
		 else
		   {
                           tfunc3d_data[index] = 0;      // red
                           tfunc3d_data[index + 1] = 1;  // green
                           tfunc3d_data[index + 2] = 0;  // blue
			   tfunc3d_data[index + 3] = 0;
		   }
               }         
               //tfunc3d_data[index + 3] = ((float)k / depth) * 1;  // alpha
           }
   // tfunc3d_data[0] = 198/255.0;
   // tfunc3d_data[1] = 163/255.0;
   // tfunc3d_data[2] = 0;
   // tfunc3d_data[0] = 0.1;
   // tfunc3d_data[1] = 0.5;
   // tfunc3d_data[2] = 0.7;
   tfunc3d_data[0] = 1;
   tfunc3d_data[1] = 1;
   tfunc3d_data[2] = 1;
   tfunc3d_data[3] = 0.1;
   tfunc3d.setValues( tfunc3d_data );
   tfunc3d.write( "OW_TW_2009.tfunc3d" );
    if( param.hasOption( "O" ) )
         tfunc3d.import( "OW.tfunc3d" );
    if( param.hasOption( "T" ) )
         tfunc3d.import( "OW_TW.tfunc3d" );
    if( param.hasOption( "t" ) )
      tfunc3d.import( param.tfunc_file );
    
    kun::RayCastingRenderer* renderer = new kun::RayCastingRenderer();
    
    renderer->addVolume2( volume_r );
    renderer->addVolume3( volume_v );
    renderer->set3DTransferFunction( tfunc3d );
//    renderer->disableShading();
    
    screen.registerObject( volume_s, renderer );
    //screen.background()->setColor( kvs::RGBColor(255, 255, 255) );
    screen.show();
    
    return( app.run() );   
}
